
#include "Plateau.h"

void Plateau::pivoterCaseLibre(int direction) {
	_caseLibre->pivoter(direction);
}

void Plateau::insereCaseLibre() {
	int i,j;
	Case * libreTemp;

	//Prevention contre le cas ou la rangee n'a jamais été changée depuis initialisation
	if(_rangeeCaseLibre.getNumero() ==0) _rangeeCaseLibre = Rangee(1,true,true);

	if(_rangeeCaseLibre.getEstLigne()){//Donc ligne
		i=_rangeeCaseLibre.getNumero();
		if(_rangeeCaseLibre.getSens()){//gauche vers droite
			//On insere
			libreTemp=_caseLibre;
			_caseLibre = _cases[i][6];

			//On pousse
			for(j=6;j>0;j--){
				(_cases[i][j])= (_cases[i][j-1]);
			}
			_cases[i][0] = libreTemp;
		}else{//droite vers gauche
			libreTemp=_caseLibre;
			_caseLibre=(_cases[i][0]);

			//On pousse
			for(j=0;j<6;j++){
				(_cases[i][j])= (_cases[i][j+1]);
			}
			(_cases[i][6]) = libreTemp;
		}
	}else{//Donc colonne
		j=_rangeeCaseLibre.getNumero();
		if(_rangeeCaseLibre.getSens()){//Haut vers bas
			//On insere
			libreTemp=_caseLibre;
			_caseLibre=_cases[6][j];

			//On pousse
			for(i=6;i>0;i--){
				_cases[i][j]= _cases[i-1][j];
			}
			_cases[0][j] = libreTemp;
		}else{//Bas vers haut
			libreTemp=_caseLibre;
			_caseLibre=_cases[0][j];

			//On pousse
			for(i=0;i<6;i++){
				_cases[i][j]= _cases[i+1][j];
			}
			_cases[6][j] = libreTemp;
		}
	}
}

vector<Case*> Plateau::casesAccessibles(const Case* depart) {
	vector<Case*> vec;
	bool absente = true;
	int i =0;
	int j =0;
	int li=0;
	int co = 0;
	//On cherche la position de la case de départ.
	while(absente && i<7 && j<7){
		while(absente && j<7){
			if (_cases[i][j] == depart){
				absente = false;
				li=i; 
				co=j;				
			}
			j++;
		}
		j=0;
		i++;
	}

	//A partir de la on cherche toutes les cases accessibles depuis cette position
	casesAccessibles(li,co,&vec);

	//On efface le premier element de vec (Qui est forcément la case de départ)
	//Pour eviter que le joueur reste sur place
	vec.erase(vec.begin());
	return vec;
}

void Plateau::casesAccessibles(int ligne, int colonne,vector<Case*>* vec){
	//Si on a pas encore testé cette case
	Case * c = _cases[ligne][colonne];
	if(!casePresente(c,vec)){
		vec->push_back(c);
		if(c->estAccessible(haut)){
			if(ligne>0){
				if(getCase(ligne-1,colonne)->estAccessible(bas))
					casesAccessibles(ligne-1,colonne,vec);
			}
		}
		if(c->estAccessible(droite)){
			if(colonne<6){
				if(getCase(ligne,colonne+1)->estAccessible(gauche))
					casesAccessibles(ligne,colonne+1,vec);
			}
		}
		if(c->estAccessible(bas)){
			if(ligne<6){
				if(getCase(ligne+1,colonne)->estAccessible(haut))
					casesAccessibles(ligne+1,colonne,vec);
			}
		}
		if(c->estAccessible(gauche)){
			if(colonne>0){
				if(getCase(ligne,colonne-1)->estAccessible(droite))
					casesAccessibles(ligne,colonne-1,vec);
			}
		}
	}
}

bool Plateau::casePresente(Case * _case,vector<Case*>* vec){
	bool presente = false;
	unsigned int i = 0;
	while(!presente && i<vec->size()){
		if(_case == vec->at(i)){
			presente = true;
		}
		i++;
	}
	return presente;
}

Case* Plateau::getCaseLibre() {
	return _caseLibre;
}


Case * Plateau::getCase(int i, int j){
	if(i>=0 && i<7 && j>=0 && j<7) return _cases[i][j];
	else return NULL;
}

vector<vector<Case*> > Plateau::getTable() {
	return _cases;
}

Rangee Plateau::getRangeeCaseLibre() {
	return _rangeeCaseLibre;
}

void Plateau::setRangeeCaseLibre(Rangee r) {
	int indice = r.getNumero();
	if((indice%2) == 1  && indice >0 && indice<7){
		_rangeeCaseLibre=r;
	}
}

Case* Plateau::caseAleatoire(vector<Case*>* vec){
	int k = rand()%vec->size();
	Case* temp= vec->at(k);
	vec->erase(vec->begin() + k);
	return temp;
}

Plateau::Plateau(){
	_caseLibre=NULL;
}
Plateau::Plateau(Tresor tres[]){
	/* Variables pour les boucles sur les lignes, colonnes, cases.*/
	int l=0;
	int j=0;
	Tresor t;
	srand(time(NULL));

	/*Vecteur contenant toutes les cases mobiles possibles.*/
	vector<Case*> cases;
	while(l<12){
		cases.push_back(new CaseI(rand()%4,NULL));
		l++;
	}
	while(l<(12+6)){
		cases.push_back(new CaseL(rand()%4,&tres[j]));
		tres[j].setCase(cases.back());
		l++;
		j++;
	}
	while(l<(12+16)){
		cases.push_back(new CaseL(rand()%4,NULL));
		l++;
	}
	while(l<(12+16+6)){
		cases.push_back(new CaseT(rand()%4,&tres[j]));
		tres[j].setCase(cases.back());
		l++;
		j++;
	}

	_rangeeCaseLibre =  Rangee::Rangee(0,true,true);

	/*Creation de _cases (le plateau reel)*/
	_cases = vector<vector<Case*> >();
	for(int i=0;i<7;i++)
		_cases.push_back(vector<Case*>());

	_cases[0].push_back(new CaseDepart(droite));
	_cases[0].push_back(caseAleatoire(&cases));
	_cases[0].push_back(new CaseT(haut,&tres[j++]));
	_cases[0].push_back(caseAleatoire(&cases));
	_cases[0].push_back(new CaseT(haut,&tres[j++]));
	_cases[0].push_back(caseAleatoire(&cases));
	_cases[0].push_back(new CaseDepart(bas));

	_cases[1].push_back(caseAleatoire(&cases));
	_cases[1].push_back(caseAleatoire(&cases));
	_cases[1].push_back(caseAleatoire(&cases));
	_cases[1].push_back(caseAleatoire(&cases));
	_cases[1].push_back(caseAleatoire(&cases));
	_cases[1].push_back(caseAleatoire(&cases));
	_cases[1].push_back(caseAleatoire(&cases));

	_cases[2].push_back(new CaseT(gauche,&tres[j++]));
	_cases[2].push_back(caseAleatoire(&cases));
	_cases[2].push_back(new CaseT(gauche,&tres[j++]));
	_cases[2].push_back(caseAleatoire(&cases));
	_cases[2].push_back(new CaseT(haut,&tres[j++]));
	_cases[2].push_back(caseAleatoire(&cases));
	_cases[2].push_back(new CaseT(droite,&tres[j++]));

	_cases[3].push_back(caseAleatoire(&cases));
	_cases[3].push_back(caseAleatoire(&cases));
	_cases[3].push_back(caseAleatoire(&cases));
	_cases[3].push_back(caseAleatoire(&cases));
	_cases[3].push_back(caseAleatoire(&cases));
	_cases[3].push_back(caseAleatoire(&cases));
	_cases[3].push_back(caseAleatoire(&cases));

	_cases[4].push_back(new CaseT(gauche,&tres[j++]));
	_cases[4].push_back(caseAleatoire(&cases));
	_cases[4].push_back(new CaseT(bas,&tres[j++]));
	_cases[4].push_back(caseAleatoire(&cases));
	_cases[4].push_back(new CaseT(droite,&tres[j++]));
	_cases[4].push_back(caseAleatoire(&cases));
	_cases[4].push_back(new CaseT(droite,&tres[j++]));

	_cases[5].push_back(caseAleatoire(&cases));
	_cases[5].push_back(caseAleatoire(&cases));
	_cases[5].push_back(caseAleatoire(&cases));
	_cases[5].push_back(caseAleatoire(&cases));
	_cases[5].push_back(caseAleatoire(&cases));
	_cases[5].push_back(caseAleatoire(&cases));
	_cases[5].push_back(caseAleatoire(&cases));

	_cases[6].push_back(new CaseDepart(haut));
	_cases[6].push_back(caseAleatoire(&cases));
	_cases[6].push_back(new CaseT(bas,&tres[j++]));
	_cases[6].push_back(caseAleatoire(&cases));
	_cases[6].push_back(new CaseT(bas,&tres[j++]));
	_cases[6].push_back(caseAleatoire(&cases));
	_cases[6].push_back(new CaseDepart(gauche));

	_caseLibre = cases[0];
}

void Plateau::affiche(){
	int i,j;
	for(i=0;i<7;i++){
		for(j=0;j<7;j++){
			cout << _cases[i][j]->toString();
		}
		cout << endl;
	}
	cout << "La case libre est " << _caseLibre->toString()<< endl << endl;
}

